﻿using System;
using System.IO;
using SeasideResearch.LibCurlNet;

namespace OccupierArchiver.Helpers
{
    internal sealed class CurlDownloader : IDisposable
    {
        private bool _disposed;
        private FileStream _fs;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public static void GlobalInit()
        {
            Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);
        }

        public static void GlobalCleanup()
        {
            Curl.GlobalCleanup();
        }

        private int OnWriteData(byte[] buf, int size, int nmemb, object extraData)
        {
            foreach (byte b in buf) _fs.WriteByte(b);
            return buf.Length;
        }

        public void DownloadFile(string url, string path)
        {
            try
            {
                _fs = new FileStream(path, FileMode.Create);

                var easy = new Easy();
                Easy.WriteFunction parameter = OnWriteData;
                easy.SetOpt(CURLoption.CURLOPT_URL, url);
                easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, parameter);

                CURLcode result = easy.Perform();
                easy.Cleanup();
                _fs.Flush();
                _fs.Close();

                if (result != CURLcode.CURLE_OK)
                    throw new Exception(result.ToString());
            }
            catch (AccessViolationException)
            {
                throw new InvalidOperationException();
            }
        }

        private void Dispose(bool disposing)
        {
            if (_disposed) return;

            if (disposing)
            {
                if (_fs != null)
                    _fs.Dispose();
                _fs = null;
            }

            _disposed = true;
        }

        ~CurlDownloader()
        {
            Dispose(false);
        }
    }
}
